package com.hopes.bizz.risk.control.support;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskEntity;
import com.hopes.bizz.risk.control.entity.RiskUnitEventEntity;
import com.hopes.bizz.risk.control.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @Description 风险管控excel导出支撑类
 * @time 2023/7/31 11:23
 */
@Component("riskDetailedExcelSupport")
public class RiskExportExcelSupport {

    /**
     * 风险辨识数据
     * @param riskControlMeasureVOList  风险管控措施
     * @return                          结果集
     */
    public List<RiskIdentifyExcelVO> IdentifyData(List<RiskControlMeasureVO> riskControlMeasureVOList) throws Exception {
        /* 构建结果集 */
        final List<RiskIdentifyExcelVO> list = new ArrayList<>();
        if (CollUtil.isEmpty(riskControlMeasureVOList)) {
            return list;
        }
        for (RiskControlMeasureVO controlMeasureVO : riskControlMeasureVOList) {
            final RiskUnitEventVO riskUnitEvent = controlMeasureVO.getRiskUnitEvent();
            final List<RiskMeasureTaskConfigVO> riskMeasureTaskConfigList = controlMeasureVO.getRiskMeasureTaskConfigList();
            list.addAll(buildExcelData(controlMeasureVO, riskUnitEvent, riskMeasureTaskConfigList, RiskIdentifyExcelVO.class));
        }
        if (CollectionUtil.isEmpty(list)) {
            return list;
        }
        /*final List<Long> collect = list.parallelStream().map(RiskIdentifyExcelVO::getControlMeasureId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        final Map<Long, List<RiskIdentifyExcelVO>> listMap = list.parallelStream().filter(e -> Objects.nonNull(e.getControlMeasureId())).collect(Collectors.groupingBy(RiskIdentifyExcelVO::getControlMeasureId));
        for (int i = 0; i < collect.size(); i++) {
            for (RiskIdentifyExcelVO riskIdentifyExcelVO : listMap.get(collect.get(i))) {
                riskIdentifyExcelVO.setIndex(String.valueOf(i + 1));
            }
        }*/
        return list.stream().sorted(Comparator.comparing(
                RiskIdentifyExcelVO::getControlMeasureId).thenComparing(
                RiskIdentifyExcelVO::getRiskEventId)).collect(Collectors.toList());
    }


    /**
     * 风险管控清单数据
     * @param riskControlMeasureVOList   风险管控数据
     * @param unitEventMap               风险事件map
     * @return                           结果集
     * @throws Exception                 异常
     */
    public List<RiskDetailExcelVO> detailedData(List<RiskControlMeasureVO> riskControlMeasureVOList, Map<Long, RiskUnitEventEntity> unitEventMap) throws Exception {
        // 构建结果集
        final List<RiskDetailExcelVO> list = new ArrayList<>();
        if (CollUtil.isEmpty(riskControlMeasureVOList)) {
            return list;
        }
        for (RiskControlMeasureVO controlMeasureVO : riskControlMeasureVOList) {
            final RiskUnitEventEntity eventEntity = MapUtil.get(unitEventMap, controlMeasureVO.getRiskEventId(), RiskUnitEventEntity.class, null);
            if (null == eventEntity) {
                continue;
            }
            final RiskUnitEventVO riskUnitEventVO = new RiskUnitEventVO();
            BeanUtils.copyProperties(eventEntity, riskUnitEventVO);
            final List<RiskMeasureTaskConfigVO> riskMeasureTaskConfigList = controlMeasureVO.getRiskMeasureTaskConfigList();
            list.addAll(buildExcelData(controlMeasureVO, riskUnitEventVO, riskMeasureTaskConfigList, RiskDetailExcelVO.class));
        }
        if (CollectionUtil.isEmpty(list)) {
            return list;
        }
        /*final LinkedHashSet<Long> controlIdSet = list.parallelStream()
                .map(RiskDetailExcelVO::getRiskObjectId).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
        final Map<Long, List<RiskDetailExcelVO>> collectMap = list.parallelStream()
                .filter(e -> Objects.nonNull(e.getRiskObjectId())).collect(Collectors.groupingBy(RiskDetailExcelVO::getRiskObjectId));

        final List<Long> controlIdList = new ArrayList<>(controlIdSet);
        for (int i = 0; i < controlIdList.size(); i++) {
            for (RiskDetailExcelVO riskDetailExcelVO : collectMap.get(controlIdList.get(i))) {
                riskDetailExcelVO.setIndex(String.valueOf(i + 1));
            }
        }*/
        return list.parallelStream().sorted(
                Comparator.comparing(RiskDetailExcelVO::getRiskObjectId)
                        .thenComparing(RiskDetailExcelVO::getRiskUnitId)
                        .thenComparing(RiskDetailExcelVO::getUnitEventId)
                        .thenComparing(RiskDetailExcelVO::getControlMeasureId)
                        .thenComparing(RiskDetailExcelVO::getTaskCheckContentId)).collect(Collectors.toList());
    }

    private <T> List<T> buildExcelData(
            RiskControlMeasureVO controlMeasureVO, RiskUnitEventVO riskUnitEventVO, List<RiskMeasureTaskConfigVO> riskMeasureTaskConfigList, Class<T> clazz) throws Exception {
        final List<T> list = new ArrayList<>();
        if (null == riskUnitEventVO) {
            return list;
        }
        final Constructor<T> declaredConstructor = clazz.getDeclaredConstructor(RiskControlMeasureVO.class, RiskUnitEventVO.class, RiskMeasureTaskConfigVO.class, RiskMeasureTaskEntity.class);
        if (CollectionUtil.isEmpty(riskMeasureTaskConfigList)) {
            list.add(declaredConstructor.newInstance(controlMeasureVO, riskUnitEventVO, null, null));
            return list;
        }
        for (RiskMeasureTaskConfigVO taskConfigVO : riskMeasureTaskConfigList) {
            final List<RiskMeasureTaskEntity> riskMeasureTaskList = taskConfigVO.getRiskMeasureTaskList();
            if (CollectionUtil.isEmpty(riskMeasureTaskList)) {
                list.add(declaredConstructor.newInstance(controlMeasureVO, riskUnitEventVO, taskConfigVO, null));
            } else {
                for (RiskMeasureTaskEntity riskMeasureTaskEntity : riskMeasureTaskList) {
                    list.add(declaredConstructor.newInstance(controlMeasureVO, riskUnitEventVO, taskConfigVO, riskMeasureTaskEntity));
                }
            }
        }
        return list;
    }


}
